package com.course.service.impl;

import static org.hamcrest.CoreMatchers.both;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.course.entity.Course;
import com.course.entity.CourseExample;
import com.course.entity.Login;
import com.course.entity.SelectedCourse;
import com.course.entity.SelectedCourseExample;
import com.course.entity.Student;
import com.course.entity.StudentExample;
import com.course.entity.Teacher;
import com.course.entity.dto.CourseInfo;
import com.course.repository.CourseRepository;
import com.course.repository.LoginRepository;
import com.course.repository.SelectedCourseRepository;
import com.course.repository.StudentRepository;
import com.course.repository.TeacherRepository;
import com.course.service.CourseService;
import com.course.service.SelectedCourseService;

@Service
public class CourseServiceImpl implements CourseService {

	@Autowired
	TeacherRepository teacherRepository;

	@Autowired
	CourseRepository courseRepository;

	@Autowired
	SelectedCourseRepository scRepository;

	@Autowired
	StudentRepository studentRepository;

	@Autowired
	CourseService _this;

	@Override
	public void addExperimentCourse(Course course) {
		course.setType(1);
		course.setState(0);
		courseRepository.insert(course);
	}

	@Override
	public void addNormalCourse(Course course) {
		course.setType(0);
		course.setState(0);
		courseRepository.insert(course);
	}

	@Override
	public void updateCourseState(Integer id, Integer state) {
		Course c = courseRepository.selectByPrimaryKey(id);
		if (c != null) {
			c.setState(state);
			courseRepository.updateByPrimaryKeySelective(c);
		}
	}

	@Override
	public void updateTime(Integer id, Integer startWeek, Integer endWeek, Integer dayOfWeek, Integer lesson) {
		Course c = courseRepository.selectByPrimaryKey(id);
		if (c != null) {
			c.setStartweek(startWeek);
			c.setEndweek(endWeek);
			c.setDayofweek(dayOfWeek);
			c.setLesson(lesson);
			courseRepository.updateByPrimaryKeySelective(c);
		}
	}

	@Override
	public void updateClassroom(Integer id, String classroom) {
		Course c = courseRepository.selectByPrimaryKey(id);
		if (c != null) {
			c.setClassroom(classroom);
			courseRepository.updateByPrimaryKeySelective(c);
		}
	}

	@Override
	public CourseInfo findById(Integer id) {
		Course course = courseRepository.selectByPrimaryKey(id);
		CourseInfo courseInfo = new CourseInfo();
		courseInfo.setCourse(course);
		Teacher teacher = teacherRepository.selectByPrimaryKey(course.getTno());
		courseInfo.setTeacher(teacher.getName());
		return courseInfo;
	}

	@Override
	public List<CourseInfo> findApproved() {
		List<CourseInfo> cInfos = this.findNormalByState(1);
		cInfos.addAll(this.findExperimentByState(1));
		return cInfos;
	}

	@Override
	public List<CourseInfo> findApprovedExperiment() {
		List<CourseInfo> cInfos = this.findExperimentByState(1);
		return cInfos;
	}

	@Override
	public List<CourseInfo> findExperimentByState(Integer state) {
		CourseExample e = new CourseExample();
		e.createCriteria().andTypeEqualTo(1).andStateEqualTo(state);
		List<Course> courses = courseRepository.selectByExample(e);
		return toCourseInfoList(courses);
	}

	@Override
	public List<CourseInfo> findNormalByState(Integer state) {
		CourseExample e = new CourseExample();
		e.createCriteria().andTypeEqualTo(0).andStateEqualTo(state);
		List<Course> courses = courseRepository.selectByExample(e);
		return this.toCourseInfoList(courses);
	}

	@Override
	public List<CourseInfo> findExperimentByTeacherId(Integer tId) {
		CourseExample e = new CourseExample();
		e.createCriteria().andTypeEqualTo(1).andTnoEqualTo(tId);
		List<Course> courses = courseRepository.selectByExample(e);
		return this.toCourseInfoList(courses);
	}

	@Override
	public List<CourseInfo> findNormalByTeacherId(Integer tId) {
		CourseExample e = new CourseExample();
		e.createCriteria().andTypeEqualTo(0).andTnoEqualTo(tId);
		List<Course> courses = courseRepository.selectByExample(e);
		return this.toCourseInfoList(courses);
	}

	@Override
	public List<CourseInfo> findUnapproved() {
		CourseExample e = new CourseExample();
		e.createCriteria().andStateEqualTo(0);
		List<Course> courses = courseRepository.selectByExample(e);
		return this.toCourseInfoList(courses);
	}

	@Override
	public List<CourseInfo> findUnapprovedExperiment() {
		CourseExample e = new CourseExample();
		e.createCriteria().andStateEqualTo(0).andTypeEqualTo(1);
		List<Course> courses = courseRepository.selectByExample(e);
		return this.toCourseInfoList(courses);
	}

	/**
	 * 不需要事务
	 */
	private List<CourseInfo> toCourseInfoList(List<Course> courses) {
		List<CourseInfo> cInfos = new ArrayList<>();
		for (Course c : courses) {
			CourseInfo courseInfo = new CourseInfo();
			Teacher teacher = teacherRepository.selectByPrimaryKey(c.getTno());
			if (teacher == null) {
				continue;
			}
			courseInfo.setTeacher(teacher.getName());
			courseInfo.setCourse(c);
			cInfos.add(courseInfo);
		}
		return cInfos;
	}

	@Override
	public List<CourseInfo> findApprovedAndNotSelectedNormal(Integer no) {
		SelectedCourseExample example = new SelectedCourseExample();
		example.createCriteria().andSnoEqualTo(no);
		List<SelectedCourse> list = scRepository.selectByExample(example);
		List<CourseInfo> result = _this.findNormalByState(1);
		return result.stream()
				.filter(ci -> list.stream().noneMatch(sc -> sc.getCno().equals(ci.getCourse().getNo())))
				.collect(Collectors.toList());
	}
}
